`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/10 23:14:56
// Design Name:
// Module Name: testMemory
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments: 本文件思路可用于测试 uart 部件的收发
//
//////////////////////////////////////////////////////////////////////////////////


module testUart(
  );
  logic clk;
  logic rst;

  logic we_i;
  logic[15:0] addr_i;
  logic[15:0] data_i;

  logic[15:0] data_o;
  logic tx_pin;
  logic rx_pin;

  parameter SYS_FRENCY = 50_000_000;// 时钟 50MHz
  parameter ONEBIT_CLOCK_COUNT = 32'h1B1;// 115200 传输一个bit 需要的时钟周期
  parameter BAUD_FRENCY = 115200;// 波特率

  localparam UART_STATUS = 15'h4000;
  localparam UART_TXDATA = 15'h4001;
  localparam UART_RXDATA = 15'h4002;

  uart
    #(.SYS_FRENCY(SYS_FRENCY),
      .BAUD_FRENCY(BAUD_FRENCY))
    uart (
      .clk         (clk)         ,
      .rst         (rst)         ,
      .in          (data_i)        ,
      .load        (we_i)    ,
      .address     (addr_i)    ,
      .uart_rx_pin (rx_pin) ,
      .uart_tx_pin (tx_pin) ,
      .out         (data_o)
    );

  initial
  begin
    clk=1;
    forever
    begin
      #10 clk=~clk;
    end
  end

  initial
  begin
    // 复位
    rst = 0;
    repeat(10) @(posedge clk);
    rst = 1;

    rx_pin = 1; // rx_pin 平常应该为高阻态

    we_i = 1;
    addr_i = UART_TXDATA;
    data_i = 'h48;
    repeat(1) @(posedge clk);
    we_i = 0;
    addr_i = UART_STATUS;
    repeat(1) @(posedge clk);
    assert (data_o === 16'b01) else
             $error("read tx status failed");

    // 使能读写
    we_i = 1;   // 写寄存器使能
    // 设置rx 为 receiving
    addr_i = UART_STATUS;
    data_i = 2'b00;
    repeat(1) @(posedge clk);
    we_i = 0; // 结束写寄存器
    repeat(1) @(posedge clk);
    // rx_pin 给一个下降沿开始写数据
    rx_pin = 0;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    // 8 位数据位, uart 先发低位，后发高位
    rx_pin = 1;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 0;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 1;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 0;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 1;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 1;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 0;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    rx_pin = 0;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    // 停止位
    rx_pin = 1;
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);

    addr_i = UART_STATUS;
    repeat(1) @(posedge clk);
    assert(data_o[1] === 1'b1) else
            $error("read status: cannot read");

    addr_i = UART_RXDATA;
    repeat(1) @(posedge clk);
    // 35
    assert (data_o[7:0] === 8'b00110101) else
             $error("rx 00110101 failed");

    we_i = 1;
    // 重置 STATUS
    addr_i = UART_STATUS;
    data_i = 2'b00;
    repeat(1) @(posedge clk);

    addr_i = UART_TXDATA;
    data_i = 8'b11000101;
    repeat(2) @(posedge clk);
    we_i = 0;

    addr_i = UART_STATUS;
    repeat(1) @(posedge clk);
    assert (data_o[0] === 1'b1) else
             $error("tx should be busy failed");
    repeat(ONEBIT_CLOCK_COUNT/2) @(posedge clk);
    assert (tx_pin === 0) else
             $error("TX No Start");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 1) else
             $error("TX 1 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 0) else
             $error("TX 2 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 1) else
             $error("TX 3 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 0) else
             $error("TX 4 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 0) else
             $error("TX 5 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 0) else
             $error("TX 6 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 1) else
             $error("TX 7 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 1) else
             $error("TX 8 Failed");
    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    assert (tx_pin === 1) else
             $error("TX Stop Failed");

    repeat(ONEBIT_CLOCK_COUNT) @(posedge clk);
    addr_i = UART_STATUS;
    repeat(1) @(posedge clk);
    assert (data_o[0] === 1'b0) else
             $error("tx failed");

  end
endmodule
